<HTML><HEAD>

<TITLE> Sparse Modulo-2 Matrix Routines </TITLE>

</HEAD><BODY>


<H1> Sparse Modulo-2 Matrix Routines </H1>

<P>This module implements operations on matrices in which the elements
are all 0 or 1, with addition and multiplication being done modulo 2.
The matrices are represented by doubly-linked lists of entries
representing the elements in each row and column that are 1s, with
other elements being assumed to be zero.  

<P>This is an appropriate representation when the matrices are sparse
(ie, 0s are much more frequent that 1s).  Matrices in which 0s and 1s
are about equally likely may be better handled with the <A
HREF="mod2dense.html">dense modulo-2 matrix routines</A>.  Matrices
can be converted between these two formats using the <A
HREF="mod2convert.html">module-2 matrix conversion routines</A>.

<P>All procedures in this module display an error message on standard 
error and terminate the program if passed an invalid argument (indicative
of a programming error), or if memory cannot be allocated.  Errors from 
invalid contents of a file result in an error code being returned to the 
caller, with no message being printed by this module. 


<A NAME="rep"><H2>Representation of sparse matrices</H2></A>

<P>This module represents a non-zero element of a matrix (which must have
the value 1, since these are modulo-2 matrices) by a node of type
<TT>mod2entry</TT>, which contains the row and column of the element,
pointers to the next non-zero elements above and below in its column
and to the left and the right in its row, and two double-precision
floating-point numbers called <B>pr</B> and <B>lr</B>, which are
of no significance to this module, but which are used by the routines
for <A HREF="decoding.html#prprp">decoding LDPC codes by probability
propagation</A>.

<P>The <TT>mod2sparse</TT> type represents a matrix.  It records the
number of rows and columns in the matrix, and contains arrays of
pointers to the <TT>mod2entry</TT> structures for the first non-zero
element in each row and the first non-zero element in each column.

<P>Matrices must be created by the <A
HREF="#allocate"><TT>mod2sparse_allocate</TT></A> procedure, which
returns a pointer to a <TT>mod2sparse</TT> structure.  When a matrix
is no longer needed, the space it occupies can be freed with <A
HREF="#free"><TT>mod2sparse_free</TT></A>.  Elements within a matrix,
represented by <TT>mod2entry</TT> nodes, are allocated as needed, and
if deleted, they will be reused for new elements within the same
matrix.  The space they occupy is not reusable for other matrices or
other purposes until the entire matrix is either freed, with <A
HREF="#free"><TT>mod2sparse_free</TT></A>, or cleared to all zeros,
with <A HREF="#clear"><TT>mod2sparse_clear</TT></A>, or used as
the result matrix for copying or arithmetic operations.


<P><B>Header files required</B>:
<TT>mod2sparse.h</TT>


<A NAME="dimension-sec">
<P><HR>
<CENTER><BIG>Dimension Macros</BIG></CENTER>
</A>

<HR>The following macros take a pointer to a mod2sparse structure as their
argument, and return the number of rows or the number of columns in
the matrix pointed to, which will have been fixed when the matrix was
created with <A HREF="#allocate">mod2sparse_allocate</A>:
<BLOCKQUOTE><PRE>
mod2sparse_rows(m)   /* Returns the number of rows in m */

mod2sparse_cols(m)   /* Returns the number of columns in m */
</PRE></BLOCKQUOTE>


<A NAME="traversal-sec">
<P><HR>
<CENTER><BIG>Traversal Macros</BIG></CENTER>
</A>

<HR>The following macros are used to move around a sparse matrix by
following the pointers from one non-zero element to the next or
previous non-zero element in the same row or column.  If such a
movement takes one beyond the last or before first entry in a row or
column, or if one tries to find the first or last non-zero entry in a
row or column that has no non-zero entries, the entry returned will be
a special one that can be identified using the
<TT>mod2sparse_at_end</TT> macro.  If one is already at this special
entry, moving further wraps one around to the first or last entry.

<P>The macros for finding the first or last entry in a row or column
take as their arguments a pointer to the matrix (<TT>mod2sparse
*</TT>) and a row or column index, starting at zero.  The other macros
take as their arguments a pointer to an entry (<TT>mod2entry *</TT>)
within some matrix.

<BLOCKQUOTE><PRE>
mod2sparse_first_in_row(m,i) /* Returns the first entry in row i of m */
mod2sparse_first_in_col(m,j) /* Returns the first entry in column j of m */

mod2sparse_last_in_row(m,i)  /* Returns the last entry in row i of m */
mod2sparse_last_in_col(m,j)  /* Returns the last entry in column j of m */

mod2sparse_next_in_row(e)    /* Returns the entry after e in its row */
mod2sparse_next_in_col(e)    /* Returns the entry after e in its column */

mod2sparse_prev_in_row(e)    /* Returns the entry before e in its row */
mod2sparse_prev_in_col(e)    /* Returns the entry before e in its col */

mod2sparse_row(e)            /* Returns the row index of entry e */
mod2sparse_col(e)            /* Returns the column index of entry e */

mod2sparse_at_end(e)         /* Returns 1 if e is a special entry obtained 
                                by moving past the end, returns 0 otherwise */
</PRE></BLOCKQUOTE>


<A NAME="alloc-sec">
<P><HR>
<CENTER><BIG>Allocating and Freeing Sparse Modulo-2 Matrices</BIG></CENTER>
</A>


<A NAME="allocate"><HR><B>mod2sparse_allocate</B>: 
Allocate space for a sparse module-2 matrix.</A>

<BLOCKQUOTE><PRE>
mod2sparse *mod2sparse_allocate 
( int n_rows,     /* Number of rows in matrix */
  int n_cols      /* Number of columns in matrix */
)
</PRE></BLOCKQUOTE>

Allocates space for a matrix with the given number of rows and
columns, and returns a pointer to it.  The matrix will initially
be all zero.  

<P>If there is not enough memory available, a message is displayed on
standard error and the program is terminated.  The matrix should be
freed with <A HREF="#free"><TT>mod2sparse_free</TT></A> once it is no
longer in use.

<P><A NAME="free"><HR><B>mod2sparse_free</B>: 
Free the space occupied by a sparse module-2 matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_free 
( mod2sparse *m   /* Pointer to matrix to free */
)
</PRE></BLOCKQUOTE>

Frees the space occupied by the matrix for re-use.  The pointer passed
should not be used afterward.  Note that space for the individual matrix
elements (but not the matrix as a whole) is also freed when <A
HREF="#clear"><TT>mod2sparse_clear</TT></A> is called, or the matrix
is used as the destination for other operations.


<A NAME="copy-clear-sec">
<P><HR>
<CENTER><BIG>Copying and Clearing Sparse Modulo-2 Matrices</BIG></CENTER>
</A>

<A NAME="clear"><HR><B>mod2sparse_clear</B>: 
Set all elements of a matrix to zero.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_clear
( mod2sparse *m   /* Pointer to matrix to clear */
)
</PRE></BLOCKQUOTE>

Sets all of the elements of the matrix passed to 0.  The space occupied
by the previous non-zero elements is freed for use in other matrices, or
other purposes.  The matrix itself is not freed, however.  To do that,
use <A HREF="#free"><TT>mod2sparse_free</TT></A>.


<P><A NAME="copy"><HR><B>mod2sparse_copy</B>: 
Copy the contents of one matrix to another.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_copy
( mod2sparse *m   /* Pointer to matrix to copy from */
  mod2sparse *r   /* Pointer to matrix to receive data */
)
</PRE></BLOCKQUOTE>

Copies the contents of the first matrix passed, <B>m</B>, to the
second matrix passed, <B>r</B>, which must already have been
allocated, and must have at least as many rows and columns as the
first.  If <B>r</B> is larger than <B>m</B>, its elements that have
row or column indexes greater than the dimension of <B>m</B> are set
to zeros.  

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).


<P><A NAME="copyrows"><HR><B>mod2sparse_copyrows</B>: 
Copy selected rows from one matrix to another.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_copyrows
( mod2sparse *m,  /* Pointer to matrix to copy rows from */
  mod2sparse *r,  /* Pointer to matrix in which to store data */
  int *rows       /* Indexes of rows, numbered from 0 */
)
</PRE></BLOCKQUOTE>

Copies selected rows of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many columns as <B>m</B>.  The indexes of the
rows to copy are given in order as an array of length the same as
the number of rows in <B>r</B>; duplicates are allowed.  Row
indexes start at 0.  These rows are copied to <B>r</B>, with the
row indexed by the first entry in <B>rows</B> going to the
first row of <B>r</B>, and so forth.  If <B>r</B> has more columns than 
<B>m</B>, the extra entries in each row are set to zeros.

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).


<P><A NAME="copycols"><HR><B>mod2sparse_copycols</B>: 
Copy selected columns from one matrix to another.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_copycols
( mod2sparse *m,  /* Pointer to matrix to copy columns from */
  mod2sparse *r,  /* Pointer to matrix in which to store data */
  int *cols       /* Indexes of columns, numbered from 0 */
)
</PRE></BLOCKQUOTE>

Copies selected columns of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many rows as <B>m</B>.  The indexes of the
columns to copy are given in order as an array of length the same as
the number of columns in <B>r</B>; duplicates are allowed.  Column
indexes start at 0.  These columns are copied to <B>r</B>, with the
column indexed by the first entry in <B>cols</B> going to the
first column of <B>r</B>, and so forth.  If <B>r</B> has more rows than 
<B>m</B>, the extra entries in each column are set to zeros.

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).


<A NAME="input-output-sec">
<P><HR>
<CENTER><BIG>Input and Output of Sparse Modulo-2 Matrices</BIG></CENTER>
</A>

<A NAME="print"><HR><B>mod2sparse_print</B>: 
Print a sparse modulo-2 matrix in human-readable form.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_print
( FILE *f,        /* File to print to */
  mod2sparse *m   /* Pointer to matrix to print */
)
</PRE></BLOCKQUOTE>

The matrix is printed on standard output with one line of output per row,
of the form
<BLOCKQUOTE><PRE>
<I>row</I>: <I>col col col ...</I>
</PRE></BLOCKQUOTE>
where <I>row</I> is the index of the row, and the <I>col</I> entries are 
the indexes of columns that are non-zero in that row.  Row and column
indexes start at zero.  Rows with no entries are printed with no column
indexes after the colon.  The number of columns is not indicated in the output. 

<P><A NAME="write"><HR><B>mod2sparse_write</B>: 
Write a sparse modulo-2 matrix to a file in machine-readable format.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_write
( FILE *f,        /* File to write data to */
  mod2sparse *m   /* Pointer to matrix write out */
)
</PRE></BLOCKQUOTE>

Writes a machine-readable representation the sparse matrix <B>m</B> to
the file <B>f</B>.  The file should have been opened in binary mode
(with a "b" in the mode passed to fopen).  The contents written will
not be text, and will not be human-readable.  Other binary data may
precede or follow the data for the matrix written.  

<P>The data written to the file starts with the number of rows and the
number of columns.  Following this are negative integers giving row
indexes (starting at 1), which apply until the next row index, and
positive integers giving column indexes (starting at 1) for a non-zero
entry in the matrix.  The data should be readable by <A
HREF="#read"><TT>mod2sparse_read</TT></A> even on a machine with a
different byte-ordering.

<P>The value returned by <TT>mod2sparse_write</TT> is one if the
operation was successful, zero if an error of some sort occurred.

<P><A NAME="read"><HR><B>mod2sparse_read</B>: 
Read a sparse modulo-2 matrix from a file.</A>

<BLOCKQUOTE><PRE>
mod2sparse *mod2sparse_read
( FILE *f,        /* File to read data from */
)
</PRE></BLOCKQUOTE>

Reads a sparse modulo-2 matrix from the file <B>f</B>.  This file
should have been opened in binary mode (with a "b" in the mode passed
to fopen).  The contents of the file at the point when
<TT>mod2sparse_read</TT> is called should have been written by <A
HREF="#write"><TT>mod2sparse_write</TT></A>.  Other binary data may
precede or follow this data.

<P>The value returned is a pointer to the matrix read, for which space
will have been allocated by <TT>mod2sparse_read</TT>, or zero if an
error occurred (either an error reading the file, or data not in the
right format).


<A NAME="elementary-sec">
<P><HR>
<CENTER><BIG>Elementary Operations on Sparse Modulo-2 Matrices</BIG></CENTER>
</A>

<A NAME="find"><HR><B>mod2sparse_find</B>: 
Look for an entry at a given row and column.</A>

<BLOCKQUOTE><PRE>
mod2entry *mod2sparse_find
( mod2sparse *m,  /* Matrix in which to look for entry */
  int row,        /* Row index (from 0) */
  int col         /* Column index (from 0) */
)
</PRE></BLOCKQUOTE>

Looks for an entry at the given row and column in the matrix <B>m</B>,
representing a non-zero element (ie, one with value 1).  Returns a
pointer to this entry if it exists, or zero (a null pointer) if it 
does not exist (ie, if that element of the matrix has value 0).

<P>The search strategy is to first look at the end of the row and the
end of the column.  The entry might be found at one of these two
places, or it might be determinable from these end entries that no
entry exists at the given row and column.  Otherwise, searches are
done from the start of the row and the start of the column, in
parallel, until an entry with the given row and column are found, or
until it can be determined that such an entry does not exist.
Searching in parallel ensures that the operation will be fast if
either the row is sparse or the column is sparse.

<P><A NAME="insert"><HR><B>mod2sparse_insert</B>: 
Insert an entry at a given row and column.</A>

<BLOCKQUOTE><PRE>
mod2entry *mod2sparse_insert
( mod2sparse *m,  /* Matrix in which to insert an entry */
  int row,        /* Row index (from 0) */
  int col         /* Column index (from 0) */
)
</PRE></BLOCKQUOTE>

Adds a new entry (representing an element with value 1) at the given
row and column position in the matrix <B>m</B>.  If such an entry
already exists, nothing is done (this is not considered to be an
error).  The new (or existing) entry is returned as the value of
this procedure.

<P>The search strategy is to first look at the end of the row for an
existing entry or for the place where the new entry belongs.  If this
fails, the row is searched from the beginning.  If an existing entry
is found, it is returned.  Otherwise, a new entry is created, it is
inserted in its correct place in the row, and it is inserted in its
correct place in its column, once again by first looking at the end,
and then if required searching from the beginning.  

<P>The effect of this strategy is that a sparse matrix can be efficiently
created by either adding entries in increasing order by row and column or in
decreasing order by row and column.

<P><A NAME="delete"><HR><B>mod2sparse_delete</B>: 
Delete an entry from a sparse modulo-2 matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_delete
( mod2sparse *m,  /* Matrix in which to delete an entry */
  mod2entry *e    /* Entry to delete - MUST be in m */
)
</PRE></BLOCKQUOTE>

Deletes the entry <B>e</B> from the sparse matrix <B>m</B>, which
effectively sets to zero the element of the matrix that this entry
corresponded to.  The entry is freed for future use in the same
matrix, but not (immediately, at least) for use in other matrices, or
generally.  The pointer to this entry should not be used again once
it is deleted.

<P>The time required for this operation does not depend on how many
entries are currently in the matrix.

<P><B>Warning:</B> It is an error if <B>e</B> is not an entry of
<B>m</B>.  This error is not currently diagnosed, but doing this may
cause serious problems, as it may lead later to entries for <B>m</B>
being erroneously freed when the matrix to which <B>e</B> properly
belongs is freed.

<A NAME="arith-sec">
<P><HR>
<CENTER><BIG>Sparse Modulo-2 Matrix Arithmetic and Comparison</BIG></CENTER>
</A>

<A NAME="transpose"><HR><B>mod2sparse_transpose</B>: 
Compute the transpose of a sparse modulo-2 matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_transpose
( mod2sparse *m,  /* Matrix to compute transpose of */
  mod2sparse *r   /* Result of transpose operation */
)
</PRE></BLOCKQUOTE>

Stores the transpose of its first argument, <B>m</B>, in the matrix
pointed to by its second argument, <B>r</B>, which must already have
been allocated, and which must have as many rows as <B>m</B> has
columns, and as many columns as <B>m</B> has rows.  The two matrices
<B>m</B> and <B>r</B> must not be the same (ie, the two pointers
passed must be different).  

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.

<P><A NAME="add"><HR><B>mod2sparse_add</B>: 
Add two sparse modulo-2 matrices.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_add
( mod2sparse *m1, /* Left operand of add */
  mod2sparse *m2, /* Right operand of add */
  mod2sparse *r   /* Place to store result of add */
)
</PRE></BLOCKQUOTE>

Adds matrices <B>m1</B> and <B>m2</B>, storing the result in the
matrix pointed to by <B>r</B>.  All three matrices must have the same
numbers of rows and columns.  It is permissible for <B>r</B> to be the
same as <B>m1</B> and/or <B>m2</B>.  Neither of the first two matrices is
changed by this procedure (unless they are the same as <B>r</B>).

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.


<P><A NAME="multiply"><HR><B>mod2sparse_multiply</B>: 
Multiply two sparse modulo-2 matrices.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_multiply 
( mod2sparse *m1, /* Left operand of multiply */
  mod2sparse *m2, /* Right operand of multiply */
  mod2sparse *r   /* Place to store result of multiply */
)
</PRE></BLOCKQUOTE>

Does a matrix multiplication of <B>m1</B> by <B>m2</B>, and stores the
result in the matrix pointed to by <B>r</B>.  The matrices must have
compatible numbers of rows and columns.  Neither of the first two
matrices is changed by this procedure.  The result matrix, <B>r</B>,
must not be the same as either <B>m1</B> or <B>m2</B>.

<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.

<P><A NAME="mulvec"><HR><B>mod2sparse_mulvec</B>: 
Multiply a vector by a sparse modulo-2 matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_mulvec
( mod2sparse *m,  /* Pointer to matrix to multiply by, M rows, N columns */
  char *u,        /* Pointer to unpacked vector to multiply, N long */
  char *v         /* Pointer to unpacked result vector, M long */
)
</PRE></BLOCKQUOTE>

Multiplies the vector <B>u</B> on the left by the sparse modulo-2
matrix <B>m</B>, storing the result in <B>v</B>.  Both <B>u</B> and
<B>v</B> are modulo-2 vectors, but are stored unpacked, with one bit
per char.  Any non-zero value in <B>u</B> is equivalent to '1'.  
The vectors <B>u</B> and <B>v</B> must not overlap.

<P><A NAME="equal"><HR><B>mod2sparse_equal</B>: 
Check whether two sparse modulo-2 matrices are equal.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_equal
( mod2sparse *m1, /* Pointers to the two matrices */
  mod2sparse *m2  /*   to compare                 */
)
</PRE></BLOCKQUOTE>

Returns one if every element of <B>m1</B> is equal to the
corresponding element of <B>m2</B>, and otherwise returns zero.  The
two matrices must have the same number of rows and the same number of
columns.


<A NAME="row-col-ops-sec">
<P><HR>
<CENTER><BIG>Row/Column Operations on Sparse Modulo-2 Matrices</BIG>
</CENTER></A>

<A NAME="count_row"><HR><B>mod2sparse_count_row</B>: 
Count the number of 1s in a row of a sparse matrix.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_count_row
( mod2sparse *m,  /* Pointer to matrix */
  int row         /* Index of row to count (from 0) */
)
</PRE></BLOCKQUOTE>

Returns the number of 1s in the given row of the matrix, by counting
the number of entries in that row.  

<P><A NAME="count_col"><HR><B>mod2sparse_count_col</B>: 
Count the number of 1s in a column of a sparse matrix.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_count_col
( mod2sparse *m,  /* Pointer to matrix */
  int col         /* Index of column to count (from 0) */
)
</PRE></BLOCKQUOTE>

Returns the number of 1s in the given column of the matrix, by counting
the number of entries in that column.  

<P><A NAME="add_row"><HR><B>mod2sparse_add_row</B>: 
Add a row to a row of a sparse matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_add_row
( mod2sparse *m1, /* Matrix containing row to add to */
  int row1,       /* Index in this matrix of row to add to */
  mod2sparse *m2, /* Matrix containing row to add from */
  int row2        /* Index in this matrix of row to add from */
)
</PRE></BLOCKQUOTE>

Modifies the row with index <B>row1</B> in the matrix <B>m1</B> by
adding to that row the row with index <B>row2</B> in the matrix
<B>m2</B>.  The matrix <B>m1</B> must have at least as many columns as
<B>m2</B>.  This operation is performed by inserting entries into the
row of <B>m1</B> at positions where they exist in the row of <B>m2</B>
but not in the row of <B>m1</B>, and deleting entries in the row of
<B>m1</B> that exist in the same position in the row of <B>m2</B>.
The matrix <B>m2</B> is not modified.

<P><A NAME="add_col"><HR><B>mod2sparse_add_col</B>: 
Add a column to a column of a sparse matrix.</A>

<BLOCKQUOTE><PRE>
void mod2sparse_add_col
( mod2sparse *m1, /* Matrix containing column to add to */
  int col1,       /* Index in this matrix of col to add to */
  mod2sparse *m2, /* Matrix containing column to add from */
  int col2        /* Index in this matrix of column to add from */
)
</PRE></BLOCKQUOTE>

Modifies the column with index <B>col1</B> in the matrix <B>m1</B> by
adding to that column the column with index <B>col2</B> in the matrix
<B>m2</B>.  The matrix <B>m1</B> must have at least as many rows as
<B>m2</B>.  This operation is performed by inserting entries into the
column of <B>m1</B> at positions where they exist in the column of
<B>m2</B> but not in the column of <B>m1</B>, and deleting entries in
the column of <B>m1</B> that exist in the same position in the column
of <B>m2</B>.  The matrix <B>m2</B> is not modified.


<A NAME="lu-decomp-sec">
<P><HR>
<CENTER><BIG>LU Decomposition of Sparse Modulo-2 Matrices</BIG></CENTER>
</A>

<A NAME="decomp"><HR><B>mod2sparse_decomp</B>: 
Find an LU decomposition of a sparse modulo-2 (sub-)matrix.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_decomp
( mod2sparse *A,      /* Matrix to find LU decomposition within, M by N */
  int K,              /* Size of sub-matrix to find LU decomposition of */
  mod2sparse *L,      /* Matrix in which L is stored, M by K */
  mod2sparse *U,      /* Matrix in which U is stored, K by N */
  int *rows,          /* Array where row indexes are stored, M long */
  int *cols,          /* Array where column indexes are stored, N long */
  mod2sparse_strategy strategy, /* Strategy to follow in picking rows/columns */
  int abandon_number, /* Number of columns to abandon at some point */
  int abandon_when    /* When to abandon these columns */
)
</PRE></BLOCKQUOTE>

<P>Takes as input a matrix, <B>A</B>, having <I>M</I> rows and
<I>N</I> columns, and an integer <I>K</I>.  Finds an LU decomposition
of a <I>K</I> by <I>K</I> sub-matrix of <B>A</B>.  The decomposition
is stored in the matrix <B>L</B>, with <I>M</I> rows and <I>K</I>
columns, and the matrix <B>U</B>, with <I>K</I> rows and <I>N</I>
columns.  The product of <B>L</B> and <B>U</B> will be equal to the
<I>K</I> by <I>K</I> submatrix of <B>A</B> obtained by taking only
rows and columns that are given in the first <I>K</I> elements of the
<B>rows</B> and <B>cols</B> arrays, which are set by this procedure,
with this sub-matrix distributed over the original <I>M</I> rows and
<I>N</I> columns.  Furthermore, the ordering of the row and column
indexes in these arrays will be set so that if the rows of <B>L</B>
and the columns of <B>U</B> were rearranged in this order, <B>L</B>
would be lower triangular, with zeros in rows past row <I>K</I>, and
<B>U</B> would be upper triangular, with zeros in columns past column
<I>K</I>.  The <B>rows</B> array is <I>M</I> long, and the <B>cols</B>
array is <I>N</I> long.  The elements in both arrays after the first
<I>K</I> contain the indexes of the rows and columns not selected to
be part of the sub-matrix of <B>A</B>, in arbitrary order.

<P>The rows and columns of <B>A</B> are selected in order to try to
make the LU decomposition as sparse as possible, using the strategy
identified by the <B>strategy</B>, <B>abandon_number</B>, and
<B>abandon_when</B> parameters.  The possible strategies are
<TT>Mod2sparse_first</TT>, <TT>Mod2sparse_mincol</TT>, and
<TT>Mod2sparse_minprod</TT>.  If <B>abandon_number</B> is greater than
zero, it is possible that the matrix will appear to have linearly
dependent rows when it actually does not.  See the <A
HREF="sparse-LU.html">discussion of sparse LU decomposition
methods</A> for details about these strategies.

<P>If <B>A</B> is not of rank <I>K</I> or more, <B>L</B> will contain
some number less than <I>K</I> of non-zero columns, and <B>U</B> will
contain an equal number of non-zero rows.  The entries in the
<B>rows</B> and <B>cols</B> arrays for the extra zero rows or columns
will be arbitrary (but valid).  The number of extra zero columns is
returned as the value of this procedure (hence a return value of zero
indicates that a <I>K</I> by <I>K</I> sub-matrix of full rank was
found).

<P>The matrix <B>A</B> is not altered.  The previous contents of 
<B>L</B> and <B>U</B> are cleared. 

<P><A NAME="forward_sub"><HR><B>mod2sparse_forward_sub</B>: 
Solve a lower-triangular system by forward substitution.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_forward_sub
( mod2sparse *L,  /* Matrix that is lower triangular after reordering */
  int *rows,      /* Array of indexes (from 0) of rows for new order */
  char *x,        /* Vector on right of equation, also reordered */
  char *y         /* Place to store solution */
)
</PRE></BLOCKQUOTE>

<P>Solves the system of equations <B>Ly</B>=<B>x</B> for <B>y</B> by
forward substitution, based on <B>L</B> being lower triangular after
its rows are reordered according to the given index array.  The
vectors <B>x</B> and <B>y</B> are stored unpacked, one bit per
character.  If <B>L</B> is <I>M</I> by <I>K</I>, then <B>x</B> should
be <I>M</I> long, but only the <I>K</I> bits indexed by <B>rows</B>
are looked at.  The solution vector, <B>y</B>, must be <I>K</I> long.
Only <I>K</I> rows of <B>L</B> are used, as also determined by the
<I>K</I> indexes in the <B>rows</B> argument.  If <B>rows</B> is null,
the first <I>K</I> rows of <B>L</B> and the first <I>K</I> elements of
<B>x</B> are used.

<P>If the matrix <B>L</B> does not have 1s on its diagonal (after row
rearrangement), there may be no solution, depending on what <B>x</B>
is.  If no solution exists, this procedure returns zero, otherwise it
returns one.  Any arbitrary bits in the solution are set to zero.

<P><A NAME="backward_sub"><HR><B>mod2sparse_backward_sub</B>: 
Solve an upper-triangular system by backward substitution.</A>

<BLOCKQUOTE><PRE>
int mod2sparse_backward_sub
( mod2sparse *U,  /* Matrix that is upper triangular after reordering */
  int *cols,      /* Array of indexes (from 0) of columns for new order */
  char *y,        /* Vector on right of equation */
  char *z         /* Place to store solution, also reordered */
)
</PRE></BLOCKQUOTE>

<P>Solves <B>Uz</B>=<B>y</B> for <B>z</B> by backward substitution,
based on <B>U</B> being upper triangular after its columns are
reordered according to the given index array.  The vectors <B>y</B>
and <B>z</B> are stored unpacked, one bit per character.  If <B>U</B>
is <I>K</I> by <I>N</I>, then the solution vector, <I>z</I>, should be
<I>N</I> long, but only the <I>K</I> bits indexed by <B>cols</B> are
set.  The vector <B>y</B> must be <I>K</I> long.  Only <I>K</I> columns
of <B>U</B> are used, as also determined by the <I>K</I> indexes in
the <B>cols</B> argument.  The other columns of <B>U</B> must be zero
(this is not checked, but is necessary for the method used to work).
If <B>cols</B> is null, the first <I>K</I> columns of <B>U</B> and the
first <I>K</I> elements of <B>z</B> are used.

<P>If the  matrix <B>U</B> does  not  have 1s  on its diagonal  (after
column rearrangement) there  may be no  solution, depending on what  y
is.  If no solution exists, this procedure  returns zero, otherwise it
returns one.  Any arbitrary bits in the solution are set to zero.

<HR>

<A HREF="index.html">Back to index for LDPC software</A>

</BODY></HTML>
